﻿using System.Collections.Generic;
using ScriptObject.Player.Property;
using UnityEngine;

/// <summary>
/// 属性控制器，负责管理和计算角色的所有属性
/// </summary>
public abstract class AttributeCompAbs : MonoBehaviour
{
    /// <summary>
    /// 存储所有属性值的字典，键为属性类型，值为属性值对象
    /// </summary>
    [SerializeField] public SerializableDic<AttributeType, AttributeValue> attributes;


    /// <summary>
    /// 当前等级
    /// </summary>
    public int level = 1;


    /// <summary>
    /// 最大等级限制
    /// </summary>
    public int maxLevel = 100;


    /// <summary>
    /// 每级属性成长系数字典，定义了每个属性随等级提升的增长值
    /// </summary>
    public BaseAttribute baseAttribute;

    public SerializableDic<AttributeType, float> growthRates;

    protected abstract SerializableDic<AttributeType, float> InitGrowthRates();

    protected void Start()
    {
        growthRates = InitGrowthRates();
        attributes = new SerializableDic<AttributeType, AttributeValue>();
        InitializeAttributes(baseAttribute);
        UpdateLevelBonuses();
    }

    #region 初始化

    /// <summary>
    /// 初始化所有属性的基础值
    /// </summary>
    public void InitializeAttributes(BaseAttribute initialData)
    {
        attributes[AttributeType.MaxHP] = new AttributeValue(initialData.maxHP);
        attributes[AttributeType.MaxMP] = new AttributeValue(initialData.maxMP);
        attributes[AttributeType.Attack] = new AttributeValue(initialData.aAttack);
        attributes[AttributeType.Defense] = new AttributeValue(initialData.defense);
        attributes[AttributeType.Speed] = new AttributeValue(initialData.speed);
        attributes[AttributeType.CritRate] = new AttributeValue(initialData.critRate);
        attributes[AttributeType.CritDamage] = new AttributeValue(initialData.critDamage);
        attributes[AttributeType.DamageBonus] = new AttributeValue(initialData.damageBonus);
        attributes[AttributeType.HealingBonus] = new AttributeValue(initialData.healingBonus);
        attributes[AttributeType.DamageReduction] = new AttributeValue(initialData.damageReduction);
    }

    #endregion

    #region 等级提升

    /// <summary>
    /// 设置等级并更新属性
    /// </summary>
    /// <param name="newLevel">新等级值</param>
    public void SetLevel(int newLevel)
    {
        int oldLevel = level;
        level = Mathf.Clamp(newLevel, 1, maxLevel);
        if (oldLevel != level)
        {
            Dictionary<AttributeType, float> oldValues = new Dictionary<AttributeType, float>();
            foreach (var attr in attributes)
            {
                oldValues[attr.Key] = attr.Value.FinalValue();
            }

            UpdateLevelBonuses();

            foreach (var attr in attributes)
            {
                float newValue = attr.Value.FinalValue();
                if (oldValues[attr.Key] != newValue)
                {
                    RxEventBus.Publish(new AttributeChangeEvent(attr.Key, oldValues[attr.Key], newValue));
                }
            }
        }
    }

    /// <summary>
    /// 更新等级相关的属性加成
    /// 根据当前等级和成长系数计算每个属性的等级加成
    /// </summary>
    public void UpdateLevelBonuses()
    {
        foreach (var attr in attributes)
        {
            if (growthRates.TryGetValue(attr.Key, out float growthRate))
            {
                float levelBonus = growthRate * (level - 1);
                // 只更新等级加成，不影响其他加成
                attr.Value.SetLevelBonus(levelBonus);
            }
        }
    }

    #endregion

    /// <summary>
    /// 添加固定值加成
    /// </summary>
    public void AddEquipmentFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.AddEquipmentFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    public void RemoveEquipmentFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.RemoveEquipmentFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    /// <summary>
    /// 添加Buff加成
    /// </summary>
    public void AddBuffFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.AddBuffFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    public void RemoveBuffFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.RemoveBuffFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    /// <summary>
    /// 添加百分比加成
    /// </summary>
    public void AddSkillFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.AddSkillFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    public void RemoveSkillFixedValueBonus(AttributeType type, float value)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            float oldValue = attr.FinalValue();
            attr.RemoveSkillFixedBonus(value);
            RxEventBus.Publish(new AttributeChangeEvent(type, oldValue, attr.FinalValue()));
        }
    }

    /// <summary>
    /// 获取属性详细信息
    /// </summary>
    public AttributeValue GetAttributeDetails(AttributeType type)
    {
        attributes.TryGetValue(type, out var attr);
        return attr;
    }

    /// <summary>
    /// 获取属性最终值
    /// </summary>
    public float GetAttributeValue(AttributeType type)
    {
        if (attributes.TryGetValue(type, out var attr))
        {
            return attr.FinalValue();
        }

        return 0f;
    }
}